﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using VersionComparer.Base;
using VersionComparer.DataModel.Assemblies.Images;

namespace VersionComparer.DataModel.Assemblies
{
    [Serializable]
    [Order(9)]
    public class PropertyItem : AssemblyItemBase <PropertyInfo>
    {

        Accessibility getAccessibility;
        Accessibility setAccessibility;
        CodeItem getMethod;
        CodeItem setMethod;
        protected override Type AssociatedType(PropertyInfo value)
        {
            return value.PropertyType;
        }
        protected override void Initialize(PropertyInfo value)
        {
            InitializeMethods(value);
            MethodInfo [] method = value.GetAccessors();
            if (method != null && method.Length > 0)
            {
                IsVirtual = method[0].IsVirtual;
                IsAbstract= method[0].IsAbstract;
                IsFamily = method[0].IsFamily;
                IsFamilyOrAssembly = method[0].IsFamilyOrAssembly;
                IsSealed = method[0].IsFinal;
            }
            Name = value.Name;
            Text = string.Format("{2}{0} {1}", UnderlyingTypeName, Name, AccessorsAsCode);
        }

        protected override string GetFullText(PropertyInfo value)
        {
            StringBuilder builder = new StringBuilder();
            Accessibility propertyAccessibility = getAccessibility;
            if ((int)setAccessibility > (int)getAccessibility)
                propertyAccessibility = setAccessibility;
            builder.Append(AddSpaceIfNotEmpty(GetAccessibilityAsCode(propertyAccessibility)));
            builder.Append(AddSpaceIfNotEmpty(GetAccessibilityAsCode(propertyAccessibility)));
            builder.Append(UnderlyingTypeRtf);
            builder.AppendLine(" " + Name);
            builder.AppendLine("{");

            #region build get 
            if (getMethod != null)
            {
                if (getAccessibility != propertyAccessibility)
                    builder.Append(AddSpaceIfNotEmpty(GetAccessibilityAsCode(getAccessibility)));
                builder.AppendLine("get");
                builder.AppendLine("{");
                builder.AppendLine();
                builder.AppendLine("}");
            }
            #endregion build get 

            #region build set 
            
            if (setMethod != null)
            {
                if (setAccessibility != propertyAccessibility)
                    builder.Append(AddSpaceIfNotEmpty(GetAccessibilityAsCode(setAccessibility)));
                builder.AppendLine("set");
                builder.AppendLine("{");
                builder.AppendLine();
                builder.AppendLine("}");
            }
            #endregion build set 
              
            builder.AppendLine("}");

            return builder.ToString();
        }
        protected override CustomAttributeData[] GetAttributes(PropertyInfo value)
        {
            return CustomAttributeData.GetCustomAttributes(value).ToArray();
        }
        protected override bool ShowPrivate
        {
            get
            {
                return false;
            }
        }

        protected override void BuildRtf(RtfBuilder builder, bool differencesOnly, bool useParentColor)
        {
            Accessibility propertyAccessibility = getAccessibility;
            if ((int)setAccessibility > (int)getAccessibility)
                propertyAccessibility = setAccessibility;
            builder.Append(AddSpaceIfNotEmpty(GetAccessibilityAsCode(propertyAccessibility)), keywordColor);
            builder.Append(UnderlyingTypeRtf);
            builder.AppendLine(" " + Name);
            builder.AppendLine("{");
            builder.Ident();

            #region build get
            if (getMethod != null)
            {
                if (getAccessibility != propertyAccessibility)
                    builder.Append(AddSpaceIfNotEmpty(GetAccessibilityAsCode(getAccessibility)), keywordColor);
                builder.AppendLine("get", keywordColor);
                builder.AppendLine("{");
                builder.Ident();
                getMethod.GetAsRtf(builder, differencesOnly, useParentColor);
                builder.AppendLine();
                builder.DeIdent();
                builder.AppendLine("}");
            }
            #endregion build get


            #region build set

            if (setMethod != null)
            {
                if (setAccessibility != propertyAccessibility)
                    builder.Append(AddSpaceIfNotEmpty(GetAccessibilityAsCode(setAccessibility)), keywordColor);
                builder.AppendLine("set", keywordColor);
                builder.AppendLine("{");
                builder.Ident();
                setMethod.GetAsRtf(builder, differencesOnly, useParentColor);
                builder.AppendLine();
                builder.DeIdent();
                builder.AppendLine("}");
            }
            #endregion build set

            builder.DeIdent();
            builder.AppendLine("}");

        }


        private void InitializeMethods(PropertyInfo value)
        {
            MethodInfo methodInfo;
            methodInfo = value.GetGetMethod();
            if (methodInfo == null)
                methodInfo = value.GetGetMethod(true);
            if (methodInfo != null)
            {
                try
                {
                    getMethod = Create<CodeItem, MethodBody>(methodInfo.GetMethodBody());
                    getAccessibility = methodInfo == null ? Accessibility.None : GetAccessibility(methodInfo.IsPublic, methodInfo.IsAssembly, methodInfo.IsFamilyOrAssembly, methodInfo.IsFamily);
                }
                catch
                {
                    getAccessibility = Accessibility.Private;
                }
            }

            methodInfo = value.GetSetMethod();
            if (methodInfo == null)
                methodInfo = value.GetSetMethod(true);

            if (methodInfo != null)
            {
                try
                {
                    setMethod = Create<CodeItem, MethodBody>(methodInfo.GetMethodBody());
                    setAccessibility = methodInfo == null ? Accessibility.None : GetAccessibility(methodInfo.IsPublic, methodInfo.IsAssembly, methodInfo.IsFamilyOrAssembly, methodInfo.IsFamily);
                }
                catch
                {
                    setAccessibility = Accessibility.Private;
                }
            }
        }
        protected override ComparableItem[] GetChilds(PropertyInfo value)
        {
            List<ComparableItem> items = new List<ComparableItem>   ();
           
            if ( getMethod!= null )
                items.Add(getMethod);
            if (setMethod != null)
                items.Add(setMethod);
            return base.GetChilds(value);
        }

        protected override System.Drawing.Image GetSpecificImage()
        {
            return AssemblyResources.property;
        }
       

    }
}
